#include "stdafx.h"
#include "YProactor.h"
#include "YSimpleSystem.h"
#include "ISystemFactory.h"
#include "YProactorToken.h"
#include <WinSock2.h>

namespace ysimple_system
{
	

	YProactor::YProactor(void)
		: m_hIOCP(nullptr)
	{
	}

	YProactor::~YProactor(void)
	{
		for (auto& pThread : m_threads)
		{	
			PostQueuedCompletionStatus(m_hIOCP, 0, 0, &m_exitProactorToken);
		}

		for (auto& pThread : m_threads)
		{	
			pThread->join();
		}
		
		CloseHandle(m_hIOCP);
		m_hIOCP = nullptr;
	}

	bool YProactor::init(DWORD concurrentThreadCount, DWORD workerCount)
	{
		m_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, concurrentThreadCount );	
		
		if ( NULL == m_hIOCP)
		{		
			return false;
		}

		for (DWORD i = 0; i < workerCount; ++i)
		{
			THREAD_SPTR thread =  ysimple_system::getFactory().createThread() ;
			m_threads.push_back(thread);
			thread->init(*this);
			thread->start();
		}
		
		return true;
	}

	bool YProactor::associate(HANDLE	handle, void* completionKey)
	{
		if (NULL == CreateIoCompletionPort(handle, m_hIOCP, (ULONG_PTR)completionKey, 0))
		{
			if (WSAGetLastError() !=  ERROR_INVALID_PARAMETER)
			{
				return false;
			}
			
		}

		return true;
	}

	void YProactor::running()
	{
		LONG_PTR		completionKey = NULL;
		OVERLAPPED*	pOverlapped = NULL;
		DWORD			dwBytesTransfered = 0;
		
		while(1)
		{
			BOOL bReturn = ::GetQueuedCompletionStatus(
				m_hIOCP,
				&dwBytesTransfered,
				(PULONG_PTR)&completionKey,
				(OVERLAPPED**)&pOverlapped,
				INFINITE);

			YProactorToken* pToken = (YProactorToken*)pOverlapped;
			if (false == pToken->onCompleted(bReturn == TRUE ? true : false, completionKey, dwBytesTransfered))
				break;
		} // while

	}

	void YProactor::release()
	{
		delete this;
	}

}
